﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Transactions;
using System.Runtime.Remoting.Messaging;

namespace _1Dot9MasterTransactions
{
    internal sealed class TransactionalServerObjectSink : IMessageSink
    {
        // Fields
        //private static bool _bPerformance = ConfigManager.GetBoolean("PerformanceCheck");
        //private static int _PerformanceLimit = ConfigManager.GetInt32("PerformanceLimitTime");

        private static bool _bPerformance = false;
        private static int _PerformanceLimit = 60000;

        private IMessageSink _NextSink;

        private ComponentBase _TargetObject;
        private Type _TargetType;

        // Methods
        public TransactionalServerObjectSink(MarshalByRefObject targetObject, IMessageSink nextSink)
        {
            this._NextSink = nextSink;
            this._TargetObject = targetObject as ComponentBase;
            if (this._TargetObject == null)
            {
                throw new InvalidOperationException("Type should be inheried from ComponentBase class.");
            }
            this._TargetType = this._TargetObject.GetType();
        }

        private IMessage ProcessMessage(IMessage msg)
        {
            IMethodCallMessage callMsg = msg as IMethodCallMessage;
            TransactionInfo txInfo = null;
            bool processing = false;
            TransactionScope scope = null;
            Stopwatch stopwatch = null;
            if (_bPerformance)
            {
                stopwatch = new Stopwatch();
                stopwatch.Start();
            }
            if (callMsg != null)
            {
                processing = true;
                txInfo = TransactionController.EnterTransactionContext(callMsg.MethodBase, out scope);
                if (txInfo != null)
                {
                    this._TargetObject.TransactionInfo = txInfo;
                    this._TargetObject.Scope = scope;
                }
                this._TargetObject.DoActivate();
            }
            IMessage rmsg = this._NextSink.SyncProcessMessage(msg);
            if (processing)
            {
                this._TargetObject.DoDeactivate();
                IMethodReturnMessage retMsg = rmsg as IMethodReturnMessage;
                if (txInfo != null)
                {
                    this._TargetObject.TransactionInfo = null;
                    TransactionController.LeaveTransactionContext(txInfo, retMsg.Exception, scope);
                    txInfo.RawData = null;
                }
            }

            if (_bPerformance)
            {
                stopwatch.Stop();
                if (stopwatch.ElapsedMilliseconds > _PerformanceLimit)
                {
                    //LogManager.WriteInfo("VolvoITK.MRS.PerformanceCheck",
                    //    LayerOption.Framework,
                    //    string.Concat(new object[] { callMsg.MethodBase.DeclaringType.Name, ".", callMsg.MethodName, " : ", stopwatch.Elapsed })
                    //    , 0
                    //    , 0);
                }
            }
            return rmsg;
        }

        IMessageCtrl IMessageSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)
        {
            throw new NotImplementedException("Asynchronous Trnasactional Method Call is not supported.");
        }

        IMessage IMessageSink.SyncProcessMessage(IMessage msg)
        {
            return this.ProcessMessage(msg);
        }

        // Properties
        IMessageSink IMessageSink.NextSink
        {
            get
            {
                return this._NextSink;
            }
        }
    }
}
